home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / log / reserveClientLogPage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  6.3 KB  |  286 lines

  1. /*
  2.  *   $RCSfile: reserveClientLogPage.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:50 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "trace.h"
  42. #include "error.h"
  43. #include "list.h"
  44. #include "pool.h"
  45. #include "tid.h"
  46. #include "io.h"
  47. #include "lock.h"
  48. #include "object.h"
  49. #include "msgdefs.h"
  50. #include "thread.h"
  51. #include "semaphore.h"
  52. #include "latch.h"
  53. #include "link.h"
  54. #include "lsn.h"
  55. #include "bf.h"
  56. #include "volume.h"
  57. #include "openlog.h"
  58. #include "trans.h"
  59. #include "logrecs.h"
  60. #include "log.h"
  61. #include "threadstate.h"
  62. #include "util_funcs.h"
  63. #include "log_intfuncs.h"
  64. #include "log_extfuncs.h"
  65. #include "thread_funcs.h"
  66. #include "thread_globals.h"
  67. #include "log_globals.h"
  68. #include "trans_globals.h"
  69. #ifdef DEBUG
  70. #    include "io_extfuncs.h"
  71. #endif
  72.  
  73.  int
  74. reserveClientLogPage (
  75.  
  76.     TRANSREC            *transRec,
  77.     SHORTPID            *nextLogPage 
  78. )
  79. {
  80.  
  81.     OPENLOG    *openLog;
  82.     BOOL    takeCheckPoint;
  83.  
  84.     TRPRINT(TR_LOG, TR_LEVEL_1, ("reserve log page"));
  85.  
  86. again:
  87.  
  88.     /*
  89.      *    get a register pointer to the openlog structure
  90.      */
  91.     openLog = &OpenLog;
  92.  
  93.     /*
  94.      *    check the open log magic number
  95.      */
  96.     CHECK_OPENLOG_MAGIC(openLog);
  97.  
  98.     /*
  99.      *    check the transaction magic number
  100.      */
  101.     CHECK_TRANSREC_MAGIC(transRec);
  102.  
  103.     /*
  104.      *    check the state of the logging
  105.      */
  106.     switch (TransInfo.logState)    {
  107.  
  108.         case L_ACTIVE:
  109.  
  110.         /*
  111.              *    log is open and active
  112.          */
  113.             break;
  114.  
  115.         case L_RECOVER:
  116.  
  117.             /*
  118.              *    check to see if the transaction is in recovery
  119.              */
  120.             if (transRec->transState != T_RECOVER)    {
  121.  
  122.                 /*
  123.                  *    queue the request pending recovery completion
  124.                  */
  125.                 if (waitList( &(openLog->recoverList) , THREAD_LOG_RECOVERY_WAIT))    {
  126.  
  127.                     return(esmFAILURE);
  128.                 }
  129.             }
  130.             break;
  131.  
  132.         case L_QUIESCE:
  133.  
  134.             /*
  135.              *    check to see if the transaction is in abort
  136.              */
  137.             if (transRec->transState != T_ABORT)    {
  138.  
  139.                 SM_ERROR(TYPE_LOG, esmLOGDISABLED);
  140.                 return(esmFAILURE);
  141.             }
  142.             break;
  143.  
  144.         default:
  145.  
  146.             /*
  147.              *    reject the request
  148.              */
  149.             SM_ERROR(TYPE_LOG, esmLOGDISABLED);
  150.             return esmFAILURE;
  151.     }
  152.  
  153.     /*
  154.      *    If the transaction is not in the active state
  155.      *    it cannot write operation log records unless the transaction
  156.      *    is being committed.
  157.      */
  158.     if ((transRec->transState != T_ACTIVE) &&
  159.         (transRec->intent != T_COMMIT) ) {
  160.  
  161.         SM_ERROR(TYPE_USER, esmBADTRANSID);
  162.         return(esmFAILURE);
  163.     }
  164.  
  165.     /*
  166.      *    get the latch on the log
  167.      */
  168.     if (waitLatch( &(openLog->logLatch), SHARE_LATCH ))    {
  169.  
  170.         return(esmFAILURE);
  171.     }
  172.  
  173.     /*
  174.      *    check to see if the log is in use
  175.      */
  176.     if (waitSemaphore( &(openLog->writeSemaphore) ))    {
  177.  
  178.         signalLatch( &(openLog->logLatch) );
  179.         return(esmFAILURE);
  180.     }
  181.  
  182.  
  183.     /*
  184.      *    calculate to see if there is enough space to hold the 
  185.      *    log page. (sizeof(LOGRECORDHDR) is subtracted so
  186.      *    that calculateLogSpace won't complain when log pages
  187.      *    are the size of MAX_LOGREC_LEN).
  188.      */
  189.     switch ( calculateLogSpace(openLog, (openLog->usableBytes - sizeof(LOGRECORDHDR))) ) {
  190.  
  191.     case esmNOERROR:
  192.  
  193.         /* There is space */
  194.         takeCheckPoint = FALSE;
  195.         break;
  196.  
  197.     case esmFAILURE:
  198.  
  199.         /*
  200.          *  The log record is too big
  201.          */
  202.         signalSemaphore( &(openLog->writeSemaphore) );
  203.         signalLatch( &(openLog->logLatch) );
  204.         return(esmFAILURE);
  205.  
  206.     case esmNOFREELOGSPACE:
  207.  
  208.         /*
  209.          *  There is no log space and taking a checkpoint will not
  210.          *  help.
  211.          */
  212.         signalSemaphore( &(openLog->writeSemaphore) );
  213.         signalLatch( &(openLog->logLatch) );
  214.         SM_ERROR(TYPE_USER, esmNOFREELOGSPACE);
  215.         return(esmFAILURE);
  216.  
  217.     case LOG_DO_CHECKPOINT:
  218.  
  219.         /*
  220.          *  A check point is required to free up space
  221.          */
  222.         takeCheckPoint = TRUE;
  223.         break;
  224.  
  225.     default:
  226.  
  227.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  228.         return(esmFAILURE);
  229.     }
  230.  
  231.     /*
  232.      *  if a checkpoint is needed, perform it
  233.      */
  234.     if  (takeCheckPoint) {
  235.  
  236.         /*
  237.          *  give back the log synchronization
  238.          */
  239.         signalSemaphore( &(openLog->writeSemaphore) );
  240.         signalLatch( &(openLog->logLatch) );
  241.  
  242.         /* activate a checkpoint and wait for it to complete */
  243.         activateCheckpoint(TRUE, FALSE, TRUE);
  244.  
  245.         /*
  246.          *  attempt to log the record again
  247.          *  Note, it cannot be assumed that there is enough
  248.          *  space after taking the checkpoint, since other
  249.          *  transactions may have used up the space.
  250.          */
  251.         TRPRINT(TR_LOG, TR_LEVEL_2, ("returned from checkPoint"));
  252.         goto again;
  253.     }
  254.  
  255.     /*
  256.      *    See if the page is already a new page (there are no log
  257.      *    records on it).
  258.      */
  259.     if (LOG_PAGE_OFFSET(openLog->tailLSN, openLog) == 0)  {
  260.         /*
  261.          *    Tail page is new, so use it.
  262.          */
  263.         *nextLogPage = openLog->tailPid;
  264.         TRPRINT(TR_LOG, TR_LEVEL_1, 
  265.             ("Using tail page %d as client log page", openLog->tailPid));
  266.     } else {
  267.  
  268.         /* record that the log has a another dirty page to preflush */
  269.         preflushLog();
  270.  
  271.         /* potentially activate a checkpoint */
  272.         activateCheckpoint(FALSE, FALSE, FALSE);
  273.  
  274.         /*
  275.          *    Get the next page in the log
  276.          */
  277.         *nextLogPage = (openLog->tailPid + 1) % openLog->filePages;
  278.     }
  279.  
  280.     /*
  281.      *    Return success
  282.      */
  283.     return(esmNOERROR);
  284.  
  285. }
  286.